﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Workbench.Models;
using Workbench.Operations;
using Workbench.Persistance;
using Workbench.Shared;

namespace WorkbenchTests.Operations
{
    [TestClass]
    public class ExerciseOperationsTests
    {
        [TestInitialize]
        public void Setup()
        {
            TestUtility.CreateAndInitializeTempDatabase();
        }

        [TestCleanup]
        public void Teardown()
        {
            DBContext.Current.UnInitialize();
        }

        [TestMethod]
        public void ExerciseOperations_CreateTestSuite_Concordance_WorkForm()
        {
            //ProjectOperations.CreateAndOpenProject(@"C:\Users\dimitar\Desktop\test.wbdb", "Exercises");

            var rootDirectoryModel = ProjectOperations.GetRootDirectory();
            var content = @"This is a sample text. Containing the word sample two times.";

            var fileModel = ProjectOperations.AddExistingFileContent("file", content, rootDirectoryModel.RowId);
            Assert.AreEqual(content, fileModel.FileContent.Content);

            var wordModels = ConcordanceOperations.GetSuggestions("sample", SuggestionType.WordForm);
            Assert.AreEqual(1, wordModels.Count);
            var wordModel = wordModels.Single();
            Assert.AreEqual(SuggestionType.WordForm, wordModel.SuggestionType);

            var suiteModel = ExerciseOperations.CreateTestSuite("Suite1");
            Assert.AreEqual(1, suiteModel.RowId);

            var nearWords = ConcordanceOperations.GetNearWords(wordModel, SuggestionType.WordForm);
            var exercise1 = ExerciseOperations.CreateConcordancerExercise("Exercise1", nearWords, wordModel);
            Assert.AreEqual(1, exercise1.RowId);
            ExerciseOperations.AddToSuite(suiteModel, exercise1);

            Assert.AreEqual(@"sample", exercise1.Word.Content);
            Assert.AreEqual(1, exercise1.SentenceIds[0]);
            Assert.AreEqual(2, exercise1.SentenceIds[1]);
        }

        [TestMethod]
        public void ExerciseOperations_CreateTestSuite_Concordance_BaseForm()
        {
            var content = @"This is a sample text. Containing the word sample two times.";

            var fileModel = ProjectOperations.AddExistingFileContent("file", content, ProjectOperations.GetRootDirectory().RowId);
            Assert.AreEqual(content, fileModel.FileContent.Content);

            var file = ProjectOperations.GetRootDirectory().GetContextIncludedFiles().Single();
            var words = LemmatizerOperations.GetWords(file);
            var wordContaining = words.Where(x => x.GetContent() == "Containing").Single();
            LemmatizerOperations.UpdateBaseFormForWords("contain", wordContaining);

            var wordModels = ConcordanceOperations.GetSuggestions("contain", SuggestionType.BaseForm);
            Assert.AreEqual(1, wordModels.Count);
            var wordModel = wordModels.Single();
            Assert.AreEqual(SuggestionType.BaseForm, wordModel.SuggestionType);

            var suiteModel = ExerciseOperations.CreateTestSuite("Suite1");
            Assert.AreEqual(1, suiteModel.RowId);

            var nearWords = ConcordanceOperations.GetNearWords(wordModel, SuggestionType.BaseForm);
            var exercise1 = ExerciseOperations.CreateConcordancerExercise("Exercise1", nearWords, wordModel);
            Assert.AreEqual(1, exercise1.RowId);
            ExerciseOperations.AddToSuite(suiteModel, exercise1);

            Assert.AreEqual(@"contain", exercise1.Word.Content);
            Assert.AreEqual(2, exercise1.SentenceIds[0]);
        }

        [TestMethod]
        public void ExerciseOperations_GetTestSuiteByName()
        {
            ExerciseOperations.CreateTestSuite("Suite1");
            var suiteModel = ExerciseOperations.GetTestSuite("Suite1");

            Assert.AreEqual("Suite1", suiteModel.Name);
            Assert.AreEqual(1, suiteModel.RowId);
        }


        [TestMethod]
        public void ExerciseOperations_DeleteSuite()
        {
            ExerciseOperations.CreateTestSuite("Suite1");
            var suiteModel = ExerciseOperations.GetTestSuite("Suite1");

            ExerciseOperations.DeleteExerciseSuite(suiteModel);
            suiteModel = ExerciseOperations.GetTestSuite("Suite1");
            Assert.IsNull(suiteModel);
        }

        [TestMethod]
        public void ExerciseOperations_GetAllTestSuites()
        {
            ExerciseOperations.CreateTestSuite("Suite5");
            ExerciseOperations.CreateTestSuite("Suite1");
            ExerciseOperations.CreateTestSuite("Suite2");
            var result = ExerciseOperations.GetTestSuites();

            Assert.AreEqual("Suite1", result[0].Name);
            Assert.AreEqual("Suite2", result[1].Name);
            Assert.AreEqual("Suite5", result[2].Name);
        }

        [TestMethod]
        public void ExerciseOperations_LoadExercises()
        {
            var suiteModel = ExerciseOperations.CreateTestSuite("Suite1");
            var rootDirectoryModel = ProjectOperations.GetRootDirectory();
            var content = @"This is a sample text. Containing the word sample two times.";
            var fileModel = ProjectOperations.AddExistingFileContent("file", content, rootDirectoryModel.RowId);
            
            var words = LemmatizerOperations.GetWords(fileModel);
            var wordContaining = words.Where(x => x.GetContent() == "Containing").Single();
            LemmatizerOperations.UpdateBaseFormForWords("contain", wordContaining);

            var wordModel = ConcordanceOperations.GetSuggestions("sample", SuggestionType.WordForm).Single();
            var nearWords = ConcordanceOperations.GetNearWords(wordModel, SuggestionType.WordForm);
            var exercise1 = ExerciseOperations.CreateConcordancerExercise("Exercise1", nearWords, wordModel);
            ExerciseOperations.AddToSuite(suiteModel, exercise1);

            var wordModel2 = ConcordanceOperations.GetSuggestions("contain", SuggestionType.BaseForm).Single();
            var nearWords2 = ConcordanceOperations.GetNearWords(wordModel2, SuggestionType.BaseForm);
            var exercise2 = ExerciseOperations.CreateConcordancerExercise("Exercise2", nearWords2, wordModel2);
            ExerciseOperations.AddToSuite(suiteModel, exercise2);

            var retrievedSuite = ExerciseOperations.GetTestSuite(@"Suite1");
            var retrievedExercises = ExerciseOperations.GetExercises(retrievedSuite);

            Assert.AreEqual(2, retrievedExercises.Count);
            Assert.AreEqual(1, retrievedExercises[0].SentenceIds[0]);
            Assert.AreEqual(2, retrievedExercises[0].SentenceIds[1]);
            Assert.AreEqual(2, retrievedExercises[1].SentenceIds[0]);
        }

        [TestMethod]
        public void ExerciseOperations_DeleteExercise()
        {
            var suiteModel = ExerciseOperations.CreateTestSuite("Suite1");
            var rootDirectoryModel = ProjectOperations.GetRootDirectory();
            var content = @"This is a sample text. Containing the word sample two times.";
            var fileModel = ProjectOperations.AddExistingFileContent("file", content, rootDirectoryModel.RowId);

            var words = LemmatizerOperations.GetWords(fileModel);
            var wordContaining = words.Where(x => x.GetContent() == "Containing").Single();
            LemmatizerOperations.UpdateBaseFormForWords("contain", wordContaining);

            var wordModel = ConcordanceOperations.GetSuggestions("sample", SuggestionType.WordForm).Single();
            var nearWords = ConcordanceOperations.GetNearWords(wordModel, SuggestionType.WordForm);
            var exercise1 = ExerciseOperations.CreateConcordancerExercise("Exercise1", nearWords, wordModel);
            ExerciseOperations.AddToSuite(suiteModel, exercise1);

            var retrievedExercises = ExerciseOperations.GetExercises(suiteModel);
            Assert.AreEqual(1, retrievedExercises.Count);

            var wordModel2 = ConcordanceOperations.GetSuggestions("contain", SuggestionType.BaseForm).Single();
            var nearWords2 = ConcordanceOperations.GetNearWords(wordModel2, SuggestionType.BaseForm);
            var exercise2 = ExerciseOperations.CreateConcordancerExercise("Exercise2", nearWords2, wordModel2);
            ExerciseOperations.AddToSuite(suiteModel, exercise2);

            retrievedExercises = ExerciseOperations.GetExercises(suiteModel);
            Assert.AreEqual(2, retrievedExercises.Count);

            ExerciseOperations.DeleteConcordancerExercise(exercise1);

            retrievedExercises = ExerciseOperations.GetExercises(suiteModel);
            Assert.AreEqual(1, retrievedExercises.Count);

            ExerciseOperations.DeleteConcordancerExercise(exercise1);

            retrievedExercises = ExerciseOperations.GetExercises(suiteModel);
            Assert.AreEqual(1, retrievedExercises.Count);

            ExerciseOperations.DeleteConcordancerExercise(exercise2);

            retrievedExercises = ExerciseOperations.GetExercises(suiteModel);
            Assert.AreEqual(0, retrievedExercises.Count);
        }

        [TestMethod]
        public void ExerciseOperations_ExportAsPlainText()
        {
            var suiteModel = ExerciseOperations.CreateTestSuite("Suite1");
            var rootDirectoryModel = ProjectOperations.GetRootDirectory();
            var content = @"This is a sample text. Containing the word sample two times.";
            var fileModel = ProjectOperations.AddExistingFileContent("file", content, rootDirectoryModel.RowId);

            var words = LemmatizerOperations.GetWords(fileModel);
            var wordContaining = words.Where(x => x.GetContent() == "Containing").Single();
            LemmatizerOperations.UpdateBaseFormForWords("contain", wordContaining);

            var wordModel = ConcordanceOperations.GetSuggestions("sample", SuggestionType.WordForm).Single();
            var nearWords = ConcordanceOperations.GetNearWords(wordModel, SuggestionType.WordForm);
            var exercise1 = ExerciseOperations.CreateConcordancerExercise("Exercise1", nearWords, wordModel);
            ExerciseOperations.AddToSuite(suiteModel, exercise1);

            var wordModel2 = ConcordanceOperations.GetSuggestions("two", SuggestionType.WordForm).Single();
            var nearWords2 = ConcordanceOperations.GetNearWords(wordModel2, SuggestionType.WordForm);
            var exercise2 = ExerciseOperations.CreateConcordancerExercise("Exercise2", nearWords2, wordModel2);
            ExerciseOperations.AddToSuite(suiteModel, exercise2);

            var wordModel3 = ConcordanceOperations.GetSuggestions("contain", SuggestionType.BaseForm).Single();
            var nearWords3 = ConcordanceOperations.GetNearWords(wordModel3, SuggestionType.BaseForm);
            var exercise3 = ExerciseOperations.CreateConcordancerExercise("Exercise3", nearWords3, wordModel3);
            ExerciseOperations.AddToSuite(suiteModel, exercise3);

            var retrievedSuite = ExerciseOperations.GetTestSuite(@"Suite1");
            var retrievedExercises = ExerciseOperations.GetExercises(retrievedSuite);


            var exported1 = ExerciseOperations.ExportAsText(retrievedExercises[0]);
            var expected1 = string.Format(
@"Exercise1

This is a {0} text.
Containing the word {0} two times.
", ExerciseOperations.EmptyWordString);
            Assert.AreEqual(expected1, exported1);

            var exported2 = ExerciseOperations.ExportAsText(retrievedExercises[1]);
            var expected2 = string.Format(
@"Exercise2

Containing the word sample {0} times.
", ExerciseOperations.EmptyWordString);
            Assert.AreEqual(expected2, exported2);

            var exported3 = ExerciseOperations.ExportAsText(retrievedExercises[2]);
            var expected3 = string.Format(
@"Exercise3

{0} the word sample two times.
", ExerciseOperations.EmptyWordString);
            Assert.AreEqual(expected3, exported3);
        }

        [TestMethod]
        public void ExerciseOperations_ExportAsPlainText_bug1()
        {
            var suiteModel = ExerciseOperations.CreateTestSuite("Suite1");
            var rootDirectoryModel = ProjectOperations.GetRootDirectory();
            var content = @"This is a sample text. Containing the word sample two times.";
            var fileModel = ProjectOperations.AddExistingFileContent("file", content, rootDirectoryModel.RowId);

            var wordModel = ConcordanceOperations.GetSuggestions("is", SuggestionType.WordForm).Where(x => x.Content == "is").Single();
            var nearWords = ConcordanceOperations.GetNearWords(wordModel, SuggestionType.WordForm);
            var exercise1 = ExerciseOperations.CreateConcordancerExercise("Exercise1", nearWords, wordModel);
            ExerciseOperations.AddToSuite(suiteModel, exercise1);

            var retrievedSuite = ExerciseOperations.GetTestSuite(@"Suite1");
            var retrievedExercises = ExerciseOperations.GetExercises(retrievedSuite);

            var exported1 = ExerciseOperations.ExportAsText(retrievedExercises[0]);
            var expected1 = string.Format(
@"Exercise1

This ............ a sample text.
", ExerciseOperations.EmptyWordString);
            Assert.AreEqual(expected1, exported1);
        }
    }
}
